// 封装 axios
import axios from 'axios';
import store from '@/store';
import { Toast } from 'antd-mobile';
import { customHistory } from './history';
import { logout, updateToken } from '@/store/slices/login';
import { setToken } from './token';

const http = axios.create({
  // baseURL: 'http://toutiao.itheima.net/v1_0',
  baseURL: 'http://geek.itheima.net/v1_0',
  timeout: 5000,
});

// 请求拦截器
http.interceptors.request.use((config) => {
  const {
    login: { token },
  } = store.getState();

  // 除了登录请求外，其他请求统一添加 token
  if (!config.url?.startsWith('/authorizations')) {
    // 此处，需要使用 非空断言 来去掉 headers 类型中的 undefined 类型
    if (config.headers) {
      config.headers.Authorization = `Bearer ${token}`;
    }
  }

  return config;
});

// 响应拦截器
http.interceptors.response.use(undefined, async (error) => {
  // 响应失败时，会执行此处的回调函数

  if (!error.response) {
    // 网路超时
    Toast.show({
      content: '网络繁忙，请稍后再试',
      duration: 1000,
    });
    return Promise.reject(error);
  }
  // token 过期，登录超时
  if (error.response.status === 401) {
    try {
      // token失效需要用refresh-token换取新的token
      // 从redux中获取 refresh-token
      const {
        login: { refresh_token },
      } = store.getState();
      if (!refresh_token) {
        // 如果代码出现了异常，就重定向到登录页面
        Toast.show({
          content: '登录超时，请重新登录',
          duration: 1000,
          afterClose: () => {
            // 清除token
            store.dispatch(logout());
            // push方法的第二个参数，就是在路由跳转时携带的额外参数
            // 登录后还重定向到之前的页面中了
            customHistory.push('/login', {
              from: customHistory.location.pathname,
            });
          },
        });
        return;
      }
      // 如果refresh-token 存在  就换取新的token
      // 不能使用http.put而应该使用http 设置的请求拦截器
      // 请求拦截器中  就会为其添加 token  而这个token是已经过期的token
      // 所以此处使用 http 没有效果 因此  此处 我们直接使用原生的axios
      // 注意：代码执行到此处 说明 token 失效了，所以此处传入的请求头 是无效的
      // 注意：由于使用原生的axios  所以 需要自己指定完整的接口地址
      const res = await axios.put(
        'http://geek.itheima.net/v1_0/authorizations',
        null,
        {
          headers: {
            Authorization: `Bearer ${refresh_token}`,
          },
        }
      );
      const newToken = {
        refresh_token,
        token: res.data.data.token,
      };
      // 更新本地存储中的token
      setToken(newToken);
      // 更新redux中的token
      store.dispatch(updateToken(newToken));
      // 可以通过 error.config  来拿到原来要执行的操作
      // 所以此处 直接通过 http
      return http(error.config);
    } catch {
      // 如果代码出现了异常，就重定向到登录页面
      Toast.show({
        content: '登录超时，请重新登录',
        duration: 1000,
        afterClose: () => {
          // 清除token
          store.dispatch(logout());
          // push方法的第二个参数，就是在路由跳转时携带的额外参数
          // 登录后还重定向到之前的页面中了
          customHistory.push('/login', {
            from: customHistory.location.pathname,
          });
        },
      });
    }
  }

  return Promise.reject(error);
});

export { http };
